package com.triones.api.service.impl;

import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.constant.EmailCodeTypeConstants;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.redis.RedisUtils;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.domain.SysUserPost;
import com.triones.api.entity.*;
import com.triones.api.entity.bo.UpdatePwdBO;
import com.triones.api.entity.bo.WithdrawRequestBodyBO;
import com.triones.api.entity.param.*;
import com.triones.api.entity.vo.*;
import com.triones.api.mapper.*;
import com.triones.api.service.MemberService;
import com.triones.api.service.third.LeptageService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/**
 * 用户列表 -业务实现
 */
@Service
@RequiredArgsConstructor
public class MemberServiceImpl implements MemberService {

    private final MemberMapper memberMapper;

    private final CryptoWalletMapper cryptoWalletMapper;

    private final BankCardMapper bankCardMapper;

    private final InviteRecordMapper inviteRecordMapper;

    private final ApplyVipRecordMapper applyVipRecordMapper;

    private final PublicizeMemberWalletMapper publicizeMemberWalletMapper;

    private final CryptoInCommonUseAddressMapper cryptoInCommonUseAddressMapper;

    private final LeptageService leptageService;

    private final KickbackRecordMapper kickbackRecordMapper;

    private final KickbackExtractMapper kickbackExtractMapper;

    private final FaitWalletMapper faitWalletMapper;

    @Override
    public TableDataInfo<CustomMemberVO> pageList(MemberParams memberParams, PageQuery pageQuery) {
        Map<String, Object> params = memberParams.getParams();
        QueryWrapper<Object> wrapper = Wrappers.query();
        wrapper.eq(StringUtils.isNotBlank(memberParams.getStatus()),"t.status", memberParams.getStatus());
        wrapper.eq(StringUtils.isNotBlank(memberParams.getIsVip()),"t.is_vip", memberParams.getIsVip());
        wrapper.eq(StringUtils.isNotBlank(memberParams.getSex()),"t.sex", memberParams.getSex());
        wrapper.eq(StringUtils.isNotBlank(memberParams.getEmail()),"t.email", memberParams.getEmail());
        wrapper.like(StringUtils.isNotBlank(memberParams.getNickname()),"t.nickname", memberParams.getNickname());
        wrapper.or(ObjectUtil.isNotEmpty(memberParams.getKeyword()),
            qw -> qw.like("t.email",memberParams.getKeyword()).or()
                .like("t.user_no",memberParams.getKeyword()).or()
                .like("t.last_name",memberParams.getKeyword()).or()
                .like("t.first_name",memberParams.getKeyword()).or()
        );
        wrapper.between(params.get("beginTime") != null && params.get("endTime") != null,
            "t.create_time", params.get("beginTime"), params.get("endTime"));
        wrapper.orderByAsc("t.user_no");
        Page<CustomMemberVO> result = memberMapper.selectPageList(pageQuery.build(), wrapper);
        return TableDataInfo.build(result);
    }

    @Override
    public CustomMemberVO getDetail(Long uid) {
        CustomMemberVO customMemberVO = new CustomMemberVO();
        MemberVO memberVO = memberMapper.selectVoById(uid);
        BeanUtil.copyProperties(memberVO,customMemberVO);
        if (memberVO != null) {
            /**
             * 法定货币余额
             */
            LambdaQueryWrapper<FaitWalletDO> faitWalletLqw = Wrappers.lambdaQuery();
            faitWalletLqw.eq(FaitWalletDO::getUid, memberVO.getId());
            customMemberVO.setFaitWalletList(faitWalletMapper.selectVoList(faitWalletLqw));

            /**
             * 电子货币余额
             */
            LambdaQueryWrapper<CryptoWalletDO> cryptoWalletLqw = Wrappers.lambdaQuery();
            cryptoWalletLqw.eq(CryptoWalletDO::getUid, memberVO.getId());
            customMemberVO.setCryptoWalletList(cryptoWalletMapper.selectVoList(cryptoWalletLqw));

            /**
             * 实体卡、电子卡总数
             */
            customMemberVO.setPlasticCardCount(Convert.toInt(bankCardMapper.selectCount(new LambdaQueryWrapper<BankCardDO>()
                .eq(BankCardDO::getCardFormFactor, "physical_card").eq(BankCardDO::getUid,memberVO.getId())),0));
            customMemberVO.setVirtualCardCount(Convert.toInt(bankCardMapper.selectCount(new LambdaQueryWrapper<BankCardDO>()
                .eq(BankCardDO::getCardFormFactor, "virtual_card").eq(BankCardDO::getUid,memberVO.getId())),0));
        }
        return customMemberVO;
    }

    @Override
    public Boolean checkHaveApplyVip() {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前用户退出登录!");
        }
        boolean flag = false;

        MemberDO memberDO = memberMapper.selectById(loginUser.getUserId());
        Long count = inviteRecordMapper.selectCount(new LambdaQueryWrapper<InviteRecordDO>().eq(InviteRecordDO::getUid, loginUser.getUserId())
            .eq(InviteRecordDO::getIsEffective, "1"));
        if (memberDO != null) {
            if (memberDO.getIsVip().equals("0") && count >= 5) {
                flag = true;
            }
        }
        return flag;
    }

    @Override
    public boolean apiApplyVip() {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前用户退出登录!");
        }
        if (!this.checkHaveApplyVip()) {
            throw new ServiceException("您当前不具备申请成为白标用户的条件");
        }
        ApplyVipRecordDO applyVipRecordDO = new ApplyVipRecordDO();
        applyVipRecordDO.setUid(loginUser.getUserId());
        applyVipRecordDO.setCreateTime(System.currentTimeMillis());
        return applyVipRecordMapper.insert(applyVipRecordDO) > 0;
    }

    @Override
    public boolean sysSetVip(MemberDO dto) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前用户退出登录!");
        }
        MemberDO memberDO = memberMapper.selectById(dto.getId());
        if (memberDO != null) {
            if (memberDO.getIsVip().equals("0")) {
                memberDO.setIsVip("1");
                memberDO.setBecomeVipWay(dto.getBecomeVipWay());
                return memberMapper.updateById(memberDO) > 0;
            }
        }
        return true;
    }

    @Override
    public boolean auditVipApply(ApplyVipRecordDO dto) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前用户退出登录!");
        }
        ApplyVipRecordDO applyVipRecordDO = applyVipRecordMapper.selectById(dto.getId());
        if (applyVipRecordDO == null) {
            throw new ServiceException("用户申请记录不存在");
        }
        if ("0".equals(applyVipRecordDO.getAuditStatus())) {
            applyVipRecordDO.setAuditUserId(loginUser.getUserId());
            applyVipRecordDO.setAuditUserName(loginUser.getUsername());
            applyVipRecordDO.setAuditTime(System.currentTimeMillis());
            applyVipRecordDO.setAuditStatus(dto.getAuditStatus());
            applyVipRecordDO.setFailRemark(dto.getFailRemark());
            if ("1".equals(dto.getAuditStatus())) {
                MemberDO memberDO = memberMapper.selectById(applyVipRecordDO.getUid());
                if (memberDO != null) {
                    if (memberDO.getIsVip().equals("0")) {
                        memberDO.setIsVip("1");
                        memberDO.setBecomeVipWay("apply");
                        memberMapper.updateById(memberDO);
                    }
                }
            }
            return applyVipRecordMapper.updateById(applyVipRecordDO) > 0;
        }
        return false;
    }

    @Override
    public TableDataInfo<CustomApplyVipRecordVO> vipApplyPageList(ApplyVipRecordParams applyVipRecordParams, PageQuery pageQuery) {
        QueryWrapper<Object> wrapper = Wrappers.query();
        wrapper.eq(StringUtils.isNotBlank(applyVipRecordParams.getAuditStatus()),"avr.audit_status",applyVipRecordParams.getAuditStatus());
        wrapper.orderByAsc("avr.create_time");
        Page<CustomApplyVipRecordVO> result = applyVipRecordMapper.selectPageList(pageQuery.build(), wrapper);
        return TableDataInfo.build(result);
    }

    @Override
    public CustomPublicizeMemberWalletVO publicizeWalletInfo() {
        CustomPublicizeMemberWalletVO customPublicizeMemberWalletVO = new CustomPublicizeMemberWalletVO();
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前用户退出登录!");
        }
        MemberVO memberVO = memberMapper.selectVoById(loginUser.getUserId());
        BeanUtil.copyProperties(memberVO,customPublicizeMemberWalletVO);
        LambdaQueryWrapper<PublicizeMemberWalletDO> lqw = Wrappers.lambdaQuery();
        customPublicizeMemberWalletVO.setPublicizeMemberWalletVOList(publicizeMemberWalletMapper.selectVoList(lqw));
        return customPublicizeMemberWalletVO;
    }

    @Override
    public TableDataInfo<CustomInviteRecordVO> inviteMemberPageList(InviteMemberParams inviteMemberParams, PageQuery pageQuery) {
        QueryWrapper<Object> wrapper = Wrappers.query();
        wrapper.eq(StringUtils.isNotBlank(inviteMemberParams.getIsEffective()),"tir.is_effective",inviteMemberParams.getIsEffective());
        wrapper.eq("tir.uid",inviteMemberParams.getUid());
        wrapper.orderByDesc("tir.create_time");
        Page<CustomInviteRecordVO> result = inviteRecordMapper.selectPageList(pageQuery.build(), wrapper);
        return TableDataInfo.build(result);
    }

    @Override
    public List<MemberVO> list() {
        LambdaQueryWrapper<MemberDO> lqw = Wrappers.lambdaQuery();
        lqw.ne(MemberDO::getStatus, "2");
        return memberMapper.selectVoList(lqw);
    }

    @Override
    public TableDataInfo<CryptoInCommonUseAddressVO> inCommonUseAddressPageList(PageQuery pageQuery) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前用户退出登录!");
        }
        LambdaQueryWrapper<CryptoInCommonUseAddressDO> lqw = new LambdaQueryWrapper<CryptoInCommonUseAddressDO>();
        lqw.eq(CryptoInCommonUseAddressDO::getUid,loginUser.getUserId());
        lqw.eq(CryptoInCommonUseAddressDO::getDel,"0");
        lqw.orderByDesc(CryptoInCommonUseAddressDO::getCreateAt);
        Page<CryptoInCommonUseAddressVO> result = cryptoInCommonUseAddressMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addInCommonUseAddress(CryptoInCommonUseAddressDO dto) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前用户退出登录!");
        }
        dto.setCreateAt(System.currentTimeMillis());
        dto.setUid(loginUser.getUserId());
        /**
         * 发送请求
         */
        WithdrawRequestBodyBO withdrawRequestBodyBO = new WithdrawRequestBodyBO();
        BeanUtil.copyProperties(dto,withdrawRequestBodyBO);
        Map withdrawResponseMap = leptageService.withdraw(withdrawRequestBodyBO);
        if (withdrawResponseMap == null) {
            throw new ServiceException("地址创建失败");
        }
        dto.setStatus(Convert.toStr(withdrawResponseMap.get("status")));
        dto.setBeneId(Convert.toStr(withdrawResponseMap.get("beneId")));
        return cryptoInCommonUseAddressMapper.insert(dto) > 0;
    }

    @Override
    public CryptoInCommonUseAddressVO inCommonUseAddressDetail(Long id) {
        return cryptoInCommonUseAddressMapper.selectVoById(id);
    }

    @Override
    public boolean editInCommonUseAddress(CryptoInCommonUseAddressDO dto) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前用户退出登录!");
        }
        CryptoInCommonUseAddressDO cryptoInCommonUseAddressDO = cryptoInCommonUseAddressMapper.selectById(dto.getId());
        if (cryptoInCommonUseAddressDO == null) {
            throw new ServiceException("当前地址不存在");
        }
        /**
         * 发送请求
         */
        WithdrawRequestBodyBO withdrawRequestBodyBO = new WithdrawRequestBodyBO();
        BeanUtil.copyProperties(dto,withdrawRequestBodyBO);
        Map withdrawResponseMap = leptageService.withdraw(withdrawRequestBodyBO);
        if (withdrawResponseMap == null) {
            throw new ServiceException("地址修改失败");
        }
        dto.setStatus(Convert.toStr(withdrawResponseMap.get("status")));
        dto.setBeneId(Convert.toStr(withdrawResponseMap.get("beneId")));
        dto.setUpdateAt(System.currentTimeMillis());
        return cryptoInCommonUseAddressMapper.updateById(cryptoInCommonUseAddressDO) > 0;
    }

    @Override
    public TableDataInfo<CustomInviteRecordVO> apiInviteMemberPageList(String isEffective,PageQuery pageQuery) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前用户退出登录!");
        }
        QueryWrapper<Object> wrapper = Wrappers.query();
        wrapper.eq(StringUtils.isNotBlank(isEffective),"tir.is_effective",isEffective);
        wrapper.eq("tir.uid",loginUser.getUserId());
        wrapper.orderByDesc("tir.create_time");
        Page<CustomInviteRecordVO> result = inviteRecordMapper.selectPageList(pageQuery.build(), wrapper);
        return TableDataInfo.build(result);
    }

    @Override
    public TableDataInfo<KickbackRecordVO> kickbackPageList(KickbackParams kickbackParams, PageQuery pageQuery) {
        Map<String, Object> params = kickbackParams.getParams();
        LambdaQueryWrapper<KickbackRecordDO> lqw = new LambdaQueryWrapper<KickbackRecordDO>();
        lqw.eq(StringUtils.isNotEmpty(kickbackParams.getSettlementStatus()),KickbackRecordDO::getSettlementStatus,kickbackParams.getSettlementStatus());
        lqw.like(StringUtils.isNotEmpty(kickbackParams.getKeyword()),KickbackRecordDO::getSource,kickbackParams.getKeyword());
        lqw.between(params.get("beginTime") != null && params.get("endTime") != null,
            KickbackRecordDO::getCreateAt, params.get("beginTime"), params.get("endTime"));
        lqw.orderByDesc(KickbackRecordDO::getCreateAt);
        Page<KickbackRecordVO> result = kickbackRecordMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    @Override
    public TableDataInfo<KickbackExtractVO> kickbackExtractApplyPageList(KickbackExtractParams kickbackParams, PageQuery pageQuery) {
        Map<String, Object> params = kickbackParams.getParams();
        LambdaQueryWrapper<KickbackExtractDO> lqw = new LambdaQueryWrapper<KickbackExtractDO>();
        lqw.eq(KickbackExtractDO::getStatus,0)
            .eq(ObjectUtil.isNotNull(kickbackParams.getUid()),KickbackExtractDO::getUid,kickbackParams.getUid())
            .between(params.get("beginTime") != null && params.get("endTime") != null,
                KickbackExtractDO::getCreateAt, params.get("beginTime"), params.get("endTime"));
        Page<KickbackExtractVO> result = kickbackExtractMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    @Override
    public TableDataInfo<KickbackExtractVO> kickbackExtractPageList(KickbackExtractParams kickbackParams, PageQuery pageQuery) {
        Map<String, Object> params = kickbackParams.getParams();
        LambdaQueryWrapper<KickbackExtractDO> lqw = new LambdaQueryWrapper<KickbackExtractDO>();
        if (kickbackParams.getStatus() == null) {
            lqw.ne(KickbackExtractDO::getStatus,"0");
        } else {
            lqw.eq(KickbackExtractDO::getStatus,kickbackParams.getStatus());
        }
        lqw.eq(ObjectUtil.isNotNull(kickbackParams.getUid()),KickbackExtractDO::getUid,kickbackParams.getUid())
            .between(params.get("beginTime") != null && params.get("endTime") != null,
                KickbackExtractDO::getCreateAt, params.get("beginTime"), params.get("endTime"));
        Page<KickbackExtractVO> result = kickbackExtractMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    @Override
    public boolean kickbackExtractAudit(KickbackExtractDO dto) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前用户退出登录!");
        }
        KickbackExtractDO kickbackExtractDO = kickbackExtractMapper.selectById(dto.getId());
        if (kickbackExtractDO == null) {
            throw new ServiceException("收益提现审核信息不存在!");
        }
        if (!kickbackExtractDO.getStatus().equals("0")) {
            throw new ServiceException("收益提现已审核，请勿重复审核!");
        }
        kickbackExtractDO.setStatus(dto.getStatus());
        kickbackExtractDO.setFailedReason(dto.getFailedReason());
        kickbackExtractDO.setAuditUserId(loginUser.getUserId());
        kickbackExtractDO.setAuditUserName(loginUser.getUsername());
        kickbackExtractDO.setCompleteAt(System.currentTimeMillis());
        return kickbackExtractMapper.updateById(kickbackExtractDO) > 0;
    }

    @Override
    public void delInCommonUseAddress(Long id) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前用户退出登录!");
        }
        CryptoInCommonUseAddressDO cryptoInCommonUseAddressDO = cryptoInCommonUseAddressMapper.selectById(id);
        if (cryptoInCommonUseAddressDO == null) {
            throw new ServiceException("当前地址不存在");
        }
        /**
         * 发送请求
         */
        boolean delAddress = leptageService.delAddress(cryptoInCommonUseAddressDO.getBeneId());
        if (!delAddress) {
            throw new ServiceException("删除失败");
        }
        cryptoInCommonUseAddressDO.setDel("1");
        cryptoInCommonUseAddressMapper.updateById(cryptoInCommonUseAddressDO);
    }

    @Override
    public void updatePwd(UpdatePwdBO bo) {
        MemberDO memberDO = memberMapper.selectOne(new LambdaQueryWrapper<MemberDO>()
            .eq(MemberDO::getEmail,bo.getEmail()).eq(MemberDO::getStatus,"0"));
        if (memberDO == null) {
            throw new ServiceException("当前用户不存在");
        }
        long timeToLive = RedisUtils.getTimeToLive(EmailCodeTypeConstants.CW_EMAIL_PWD_UPDATE + memberDO.getEmail());
        if (timeToLive == -2) {
            throw new ServiceException("验证码已失效");
        }
        String code = Convert.toStr(RedisUtils.getCacheObject(EmailCodeTypeConstants.CW_EMAIL_PWD_UPDATE + memberDO.getEmail()),"");
        if (!code.equals(bo.getEmailCode())) {
            throw new ServiceException("验证码错误!");
        }
        if (!bo.getNewPwd().equals(bo.getConfirmPwd())) {
            throw new ServiceException("确认密码有误!");
        }
        memberDO.setPassword(BCrypt.hashpw(bo.getConfirmPwd()));
        memberMapper.updateById(memberDO);
    }
}
